package 函数式编程;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;

import 基础.HelloWorld;

import java.util.function.Consumer;
/*
public class Test {

	public static void main(String[] args) {
		Consumer<String> consumer1=new Consumer<String>() {  //有入参，无返回
			@Override
			 public void accept(String s) {
				System.out.println(s);
			}
		};
		consumer1.accept("方式一");
		Consumer<String> consumer2=(String s)->{System.out.println(s);};
		consumer2.accept("方式二");
		
		Consumer<String> consumer3=(s)->System.out.println(s);
		consumer3.accept("方式三");
		
		Consumer<String> consumer4=System.out::println;
		consumer4.accept("方式四");
		
		Supplier<String> supplier1= () -> "8"; //无入参，有返回
		System.out.println(supplier1.get());
	}

}
*/
/*
public class Test {
	public static void main(String[] args) {
		BinaryOperator<Double> operator1=new BinaryOperator<Double>(){
			@Override
			public Double apply(Double o1,Double o2) {
				return Math.max(o1,o2);//静态方法
			}
		};
		System.out.println("方式一： "+operator1.apply(2.13, 2.14));
		
		BinaryOperator<Double> operator2=(o1,o2)->{return Math.max(o1, o2);};
		System.out.println("方式二： "+operator2.apply(2.13, 2.14));
		
		BinaryOperator<Double> operator3=(Double o1,Double o2)->Math.max(o1, o2);
		System.out.println("方式三： "+operator3.apply(2.13, 2.14));
		
		BinaryOperator<Double> operator4=Math::max;//静态方法
		System.out.println("方式四： "+operator4.apply(2.13, 2.14));
	}
}
*/
/*import java.util.Comparator;
public class Test {
	public static void main(String[] args) {

//		public final class Integer extends Number implements Comparable<Integer>, Constable, ConstantDesc {
//			public static int compare(int x, int y) {
//	        return (x < y) ? -1 : ((x == y) ? 0 : 1);
//	  	  }
//		}
		
		Comparator<Integer> comparator1=new Comparator<Integer>() {
			@Override
			public int compare(Integer o1,Integer o2) {
				return Integer.compare(o1, o2);//静态方法
			}
		};
		System.out.println(comparator1.compare(3,2));//1
		
		Comparator<Integer> comparator2=Integer::compare;//int java.lang.Integer.compare(int x, int y)
		System.out.println(comparator2.compare(33,200));//-1
		
        //int java.lang.Integer.compareTo(Integer anotherInteger)
		//隐含this,实际内部调用Integer.compare(int x, int y)
		Comparator<Integer> comparator3=Integer::compareTo;
		System.out.println(comparator3.compare(33,200));//-1 
		
	}
}*/

/*import java.util.Comparator;
public class Test {//实例方法
	public static void main(String[] args) {
		Comparator<String> comparator1=new Comparator<>() {
			public int compare(String o1,String o2) {
				return o1.compareTo(o2);
			}
		};
		System.out.println(comparator1.compare("20", "30"));//-1
		
		Comparator<String> comparator2=(String o1,String o2)->(o1.compareTo(o2));
		System.out.println(comparator2.compare("30", "20"));//1
		
		Comparator<String> comparator3=String::compareTo;
		System.out.println(comparator3.compare("30", "30"));//0
	}
}*/
/*
interface ImTheOne<T>{
	String handleString(T a,String b);
}

class OneClass{
	String str;
	public String concatString(String a) {
		return this.str+a;
	}
	public String startHandleString(ImTheOne<OneClass> imtheone,String str) {
		return imtheone.handleString(this,str);
	}
}

public class Test {
    public static void main(String[] args) {
    	OneClass oneclass=new OneClass();
    	oneclass.str="abc";
    	String result=oneclass.startHandleString(OneClass::concatString, "123");
    	System.out.println(result);

    	String result1=oneclass.startHandleString((a,b)->oneclass.concatString(b), "112233");
    	System.out.println(result1);
    	
    }
}
*/
/*
interface FunctionInterfaceTest{ //可以利用UnaryOperator<T> 接口 对类型为T的对象进行一元运算，返回T类型结果     T apply(T t)
	String getInfo(String Input);
}

public class Test {//实例方法
	public static void main(String[] args) {
		FunctionInterfaceTest FiTest1=str->str+"copy";
		FunctionInterfaceTest FiTest2=Test::FunctionInterfaceTestMethod;//调用Test的静态方法
		FunctionInterfaceTest FiTest3=String::new;//直接使用String实例化  调用String之public String(String str)构造函数实例化
		
		System.out.println(useFunctionInterfaceTest("Hello World",FiTest1));
		System.out.println(useFunctionInterfaceTest("Hello World",FiTest2));
		System.out.println(useFunctionInterfaceTest("Hello World",FiTest3));
		System.out.println(useFunctionInterfaceTest("Hello World",str->str+" created by lambda in the context"));
		
		//利用UnaryOperator<T> 接口
		UnaryOperator<String> F1=str->str+"Copy";
		System.out.println(F1.apply("HelloWorld===="));
		UnaryOperator<String> F2=Test::FunctionInterfaceTestMethod;
		UnaryOperator<String> F3=String::new;
		System.out.println(useFunction("Hello World----",F1));
		System.out.println(useFunction("Hello World----",F2));
		System.out.println(useFunction("Hello World----",F3));
		System.out.println(useFunction("Hello World----",str->str+" created by lambda in the context"));
		
		UnaryOperator<Integer> F11=str->str+1000;
		System.out.println(useFunction(1000,F11));//入参为Integer
		System.out.println(F11.apply(1000));//入参为Integer
		
	}
	public static String FunctionInterfaceTestMethod(String str) {
		return str+"copy of referance.";
	}
	public static String useFunctionInterfaceTest(String str,FunctionInterfaceTest FiT) {
		return FiT.getInfo(str);
	}
	public static <K> K useFunction (K str1,UnaryOperator<K> fit) { //泛型方法  可使用String或Integer型入参
		return fit.apply(str1);
	}
}
*/

// 常用的函数式接口主要有四种类型，是通过其输入和输出的参数来进行区分的。定义了编码过程中主要的使用场景。 
// ●Function<T,R>  接收一个T类型的参数，返回一个R类型的结果              R apply(T t) 
// ●Consumer<T>    接收一个T类型的参数,不返回值                       void accept(T t); 
// ●Predicate<T>   接收一个T类型的参数，返回一个boolean类型的结果        boolean test(T t); 
// ●Supplier<T>    不接受参数，返回一个T类型的结果                     T get();
// 
// ●BiFunction<T,U,R> 对类型为T U的对象应用操作,并返回R类型的对象        R apply(T t，U u) 
// ●BiConsumer<T,U>   对类型为T,U参数应用操作,无返回                  void accept(T t,U u) 
// ●BiPredicate<T, U> 接收一个T,U类型的参数，返回一个boolean类型的结果   boolean test(T t, U u)
// 
// ●UnaryOperator<T> Function子接口 对类型为T的对象进行一元运算，返回T类型结果     T apply(T t)
// ●BinaryOperator<T> BiFunction子接口 对类型为T的对象进行二元运算,返回T类型结果  T apply(T t1，T t2)
// 
// ●ToIntFunction<T> 计算int值的函数                        int applyAsInt(T value) 
// ●IntFunction<R>   参数为int类型的函数                     R apply(int value)
// 
 
/*
interface Function<T, R> {
    R apply(T t);
}
Function<String, String> compose_function = 
((Function<String, String>) (str -> str + "abc")).compose((Function<String, String>) (str -> str + str.length()));
System.out.println("Compose function: " + compose_function.apply("Hello World! "));

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }


    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
*/

//@FunctionalInterface
//public interface Function<T, R> {
//    R apply(T t);
//}
//使用JDK内部定义的常用接口
/*
public class Test {//实例方法
	public static void main(String[] args) {
		Function<String,String> add_postfix=Str->Str+"postfix";
		Consumer<String> print_String=System.out::println;
		Predicate<Integer> judge_positive=n->n>0;
		Supplier<String> supplier=()->"suplier";
		
		System.out.println(add_postfix.apply("Function<T,R>: R apply(T t)   "));
		print_String.accept("Consumer<T>: void accept(T t)   ");
		System.out.println("Predicate<T>: boolean test(T t)   "+judge_positive.test(-4));//false
		System.out.println("Supplier<T>: T get()   "+supplier.get());
		
		List<String> list=Arrays.asList("adfsg", "sdaff", "", "s", "231243", "hgjrepjrg","0868675674765756");
		list.stream()
			.map(s->s+"1")
			.filter(s->s.length()>2) //过滤掉长度<=2的String
			.sorted((s1,s2)->s1.compareTo(s2))//从小到大排序
			.forEach(System.out::println);
			
		BiFunction<String,String,Integer> combine_String=(s1,s2)->s1.length()+s2.length();//R apply(T t，U u)
		BiConsumer<String,Integer> print_two=((s1,n1)->{System.out.println(s1);System.out.println(n1);});//void accept(T t,U u)
//		BiPredicate<String,String> String_equal=(s1,s2)->s1.equals(s2);
		BiPredicate<String,String> str_equal=String::equals;//boolean test(T t, U u)
		
		int bif_result=biFunctionTestMethod("str1","str2",(s1,s2)->(s1.length()+s2.length()));
		biConsumerTestMethod("1234", "dfgh", (str1, str2) -> System.out.println(str1 + str2));
        boolean bip_result_1 = biPredictTestMethod("abc", "abc", String::equals),
//        boolean bip_result_2 = biPredictTestMethod("abc", "def", String::equals);
                bip_result_2 = biPredictTestMethod("abc", "def", (s1,s2)->s1.equals(s2));
        System.out.println(bif_result);
        System.out.println(bip_result_1);
        System.out.println(bip_result_2);

        
      Function<String, String> compose_function = 
      ((Function<String, String>) (str -> str + "abc")).compose((Function<String, String>) (str -> str + str.length()));
      System.out.println("Compose function: " + compose_function.apply("Hello World! "));//Compose function: Hello World! 13abc

	}
	private static int biFunctionTestMethod(String str1, String str2, BiFunction<String,String,Integer> BiF) {
		return BiF.apply(str1,str2);
	}
	private static void biConsumerTestMethod(String str1, String str2, BiConsumer<String, String> BiC) {
		BiC.accept(str1,str2);
	}
	private static boolean biPredictTestMethod(String str1, String str2, BiPredicate<String,String> str_equal) {
		return str_equal.test(str1,str2);
	}
}*/
//默认方法：andThen，用来进行组合操作，
//default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
//        Objects.requireNonNull(after);
//        return (T t) -> after.apply(apply(t));
//    }

public class Test {//andThen、conpose 
	public static void main(String[] args) {
		test(msg->Integer.parseInt(msg));
		//andThen: 
		aTtest(msg1->Integer.parseInt(msg1),msg2 -> msg2*10); 
	}
	
	public static void test(Function<String,Integer> function) { //Function<T,R> R apply(T t)
		Integer apply=function.apply("666"); 
		System.out.println("apply "+apply); 
	}
 
	//andThen: 
	public static void aTtest(Function<String,Integer> f1,Function<Integer,Integer> f2) {//
		Integer i1=f1.apply("666"); 
		Integer i2=f2.apply(i1); 
		Integer i3=f1.andThen(f2).apply("666");//i2=i3 等效上面两行代码
		System.out.println(i1);//666 System.out.println(i2);//6660
		System.out.println(i3);//6660 }
	}
}

//@FunctionalInterface
//interface Predicate<T> {
//    boolean test(T t);
//
//    default Predicate<T> and(Predicate<? super T> other) {
//        Objects.requireNonNull(other);
//        return (t) -> test(t) && other.test(t);
//    }
//}
/*import java.util.function.Predicate;
public class Test {

	public static void main(String[] args) {
		test(msg -> {
			return msg.length() > 3;
		}, "HelloWorld");

		//and
		CoPtest(msg1->{
			return msg1.contains("H");
		},msg2->{
			return msg2.contains("W");
		});
	}

	private static void test(Predicate<String> predicate, String msg) {
		boolean b = predicate.test(msg);
		System.out.println("b:" + b);
	}
	
	//
	private static void CoPtest(Predicate<String> p1,Predicate<String> p2) {
		// and: p1 包含H 同时 p2 包含W
		boolean b1=p1.and(p2).test("Hello");
		System.out.println("b1:" + b1);//false
	}
}*/

/*interface MessageBuilder{
	String buildMessage();
}
public class Test {
	private static void Log(int level,MessageBuilder build) {
		if (level==1) {
			System.out.println(build.buildMessage());
		}else {
			System.out.println("未执行lambda");
			}
		
	}
	public static void main(String[] args) {
		String a="aaaa";
		String b="bbbb";
		String c="cccc";
		Log(2,()->{
			System.out.println("执行lambda");
			return a+b+c;
		});
	}
}*/

/*public class Test{
	public static void main(String[] args) {
		Power poweroftwo=new PowerOfTwo();
		Power powerofthree=new PowerOfThree();
//		BiFunction<Power,Integer,Integer> function=Power::power;
		BiFunction<Power,Integer,Integer> function=(p,i)->p.power(i);
		System.out.println(function.apply(poweroftwo,4));
		System.out.println(function.apply(powerofthree,4));
	}
}
interface Power {
	int power(int i);
}

class PowerOfTwo implements Power {
	@Override
	public int power(int i) {
		return (int)Math.pow(2, i);
	}
}

class PowerOfThree implements Power{
	public int power(int i) {
		return (int)Math.pow(3,i);
	}
}*/

/*interface StringFunc{
	String func(String n);
}

class MyStringOps{
	public static String strReverse(String str) {
		String result="";
		for (int i=str.length()-1;i>0;i--) {
			result=result+str.charAt(i);
		}
		return result;
	}
}
public class Test{
	public static String stringOp(StringFunc sf,String str) {
		return sf.func(str);
	}
	public static void main(String[] args) { 
		String inStr = "lambda add power to Java";
		String outStr=stringOp(MyStringOps::strReverse,inStr);
		System.out.println(inStr);
		System.out.println(outStr);
	}
}*/

//class Myclass{
//	private int val;
//	Myclass(int val){
//		this.val=val;
//	}
//	public int getVal() {
//		return val;
//	}
//}
//
//public class Test{
//	public static int compareMc(Myclass a,Myclass b) {
//		return a.getVal()-b.getVal();
//	}
//	public static void main(String[] args) {
//		List<Myclass> myclass=new ArrayList<>();
//		myclass.add(new Myclass(1));
//		myclass.add(new Myclass(2));
//		myclass.add(new Myclass(3));
//		myclass.add(new Myclass(4));
//		myclass.add(new Myclass(5));
//		myclass.add(new Myclass(6));
//		Myclass myclassmax=Collections.max(myclass, Test::compareMc);
//		Myclass myclassmax1=Collections.max(myclass,(a,b)->a.getVal()-b.getVal());
////		Myclass myclassmax2=Collections.max(myclass,new Comparator<Myclass>() {
////			public int compare(Myclass a,Myclass b) {
////				return a.getVal()-b.getVal();
////			}
////		});
//		System.out.println(myclassmax.getVal());
//		System.out.println(myclassmax1.getVal());
////		System.out.println(myclassmax2.getVal());
//	}
//}


//interface StringFunc{//符合Function: R apply(T t)条件，可以直接利用Function接口
//	String func(String s);
//}
/*class MyStringOps {
     public String strReverse(String str) {
		String result="";
		for (int i=str.length()-1;i>=0;i--) {
			result=result+str.charAt(i);
		}
		return result;
	}
}
public class Test{
	public static String stringOp(Function<String,String> sf,String str) {
		return sf.apply(str);
	}
	public static void main(String[] args) {
		String inStr = "lambda add power to Java";
		MyStringOps mystringops=new MyStringOps();//实例调用，输入一个String类型参数返回一个String类型结果
		String outStr=stringOp(mystringops::strReverse,inStr);
		System.out.println(inStr);
		System.out.println(outStr);
	}
}*/
//interface MyFunc<T> {
//	int func(T[] vals,T v);
//}
//class MyArrayOps{
//	public static <T> int countMatching(T[] vals,T v) {
//		int count=0;
//		for (int i=0;i<vals.length;i++) {
//			if (vals[i]==v) {
//				count++;
//			}
//		}
//		return count;
//	}
//}
//public class Test{
//	public static<T> int MyOp(BiFunction<T[],T,Integer> mf,T[] vals,T v) {
//		return mf.apply(vals,v);
//	}
//
////	public static<T> int MyOp(MyFunc<T> mf,T[] vals,T v) {
////		return mf.func(vals,v);
////	}
//	public static void main(String[] args) {
//        Integer[] vals = {1, 2, 3, 4, 2, 3, 4, 4, 5,2,3,2};
//        String[] strs = {"One", "Two", "Three", "Two","Two"};
//        int intcount=MyOp(MyArrayOps::countMatching,vals,2);
//        int strcount=MyOp(MyArrayOps::countMatching,strs,"Two");
//        System.out.println(intcount);
//        System.out.println(strcount);
//	}
//}

//类::实例方法
//这种模式并不是要直接调用类的实例方法，这样显然连编译都过不去。
//这种模式实际上是 对象::实例方法模式的一种变形，当一个对象调用方法时，方法的某个参数是函数式接口，而且函数式接口的方法参数列表的第一个参数
//就是调用者对象所属的类时，可以引用调用者类中定义的，不包含函数式接口第一个参数的方法，并用类::实例方法这种形式来表达，比如这样：
/*
interface ImTheOne<T>{
	String HandleString(T a,String b);
}
class OneClass{
	String OneString;
	public String concatString(String a) {
		return this.OneString+a;
	}
	public String startHandleString(ImTheOne<OneClass> imtheone,String str) {
		return imtheone.HandleString(this, str); 
	}
}
public class Test{
	public static void main(String[] args) {
		OneClass oneclass=new OneClass();
		oneclass.OneString="abc";

		String result=oneclass.startHandleString(OneClass::concatString,"123");
		System.out.println(result);
		
		ImTheOne<OneClass> imtheone1=(a,b)->oneclass.concatString(b);//a已经存在
		String result1=oneclass.startHandleString(imtheone1, "123");
		System.out.println(result1);

	}
}
*/
/*
interface MathOpration {
	int oprator(int x,int y);
}

public class Test{
	static int Oprator(int x,int y, MathOpration mathOpration) {
		return mathOpration.oprator(x,y);
	}
	public static void main(String[] args) {
		MathOpration addMathOpration=(x,y)->x+y;
		MathOpration subMathOpration=(x,y)->x-y;
		MathOpration mulMathOpration=(x,y)->x*y;
		MathOpration devMathOpration=(x,y)->x/y;
		System.out.println("x+y:"+addMathOpration.oprator(60, 15));
		System.out.println("x-y:"+subMathOpration.oprator(60, 15));
		System.out.println("x*y:"+mulMathOpration.oprator(60, 15));
		System.out.println("x/y:"+devMathOpration.oprator(60, 15));
	}
}
*/